Skip to content

perf(schema): compile compose-spec schema once#890

Merged
glours merged 1 commit into
compose-spec:mainfrom
ndeloof:fix/schema-validate-concurrency
Jun 29, 2026
Merged

perf(schema): compile compose-spec schema once#890
glours merged 1 commit into
compose-spec:mainfrom
ndeloof:fix/schema-validate-concurrency

Conversation

@ndeloof

@ndeloof ndeloof commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

What

schema.Validate rebuilt a jsonschema.Compiler and recompiled the embedded compose-spec.json schema — including loading and resolving the draft 2020-12 meta-schema — on every call. This commit compiles the schema once behind a sync.Once and reuses the resulting *jsonschema.Schema.

Also switches MustCompileCompile so a compilation failure is returned as an error instead of panicking, and adds a concurrent Validate regression test (run with -race).

Why

The loader calls Validate once per file on the hot path, so recompiling the full schema each time is needlessly expensive. Compiling once:

  • keeps Validate cheap (~µs/op instead of a full schema compilation per call);
  • makes Validate safe to call concurrently without sharing any mutable compiler state.

Context

Investigated while looking at docker/compose#13866 (fatal error: concurrent map iteration and map write reported inside schema compilation). Note: I could not reproduce that crash through schema.Validate — even under heavy concurrency with -race, both before and after this change, no data race fires. The current loader is sequential and each Validate call already keeps independent state, so the reported concurrency most likely originates in the caller (docker/compose). This change is therefore offered as a performance + hardening improvement rather than a fix for that specific crash; it relates to the issue without claiming to close it.

Test

  • go test -race ./schema/... passes, including the new TestValidateConcurrent (50 goroutines) and an ad-hoc hammer of 4000 concurrent validations of the real schema.

🤖 Generated with Claude Code

Validate rebuilt a jsonschema Compiler and recompiled the embedded
compose-spec schema (including loading and resolving the draft 2020-12
meta-schema) on every call. Compile it once behind a sync.Once instead,
which keeps Validate cheap on the loader hot path and makes it safe to
call concurrently without sharing any mutable compiler state.

Switch MustCompile to Compile so a schema compilation failure is
returned as an error instead of panicking. Add a concurrent Validate
test (run with -race) as a regression guard.

Relates to docker/compose#13866

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
@ndeloof ndeloof force-pushed the fix/schema-validate-concurrency branch from b1a035a to 2133283 Compare June 29, 2026 14:05

@glours glours left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@glours glours merged commit 0670a1c into compose-spec:main Jun 29, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants